package common

import (
	"app/common/dao/query"
	"app/common/redisdb"
	"app/common/sqlx"
	"app/config"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/redis/go-redis/v9"
	"gorm.io/gorm"
)

type ServiceContext struct {
	GinCtx      *gin.Context // 每个请求唯一
	DbClient    *gorm.DB
	QClient     *query.Query
	RedisClient *redis.Client
	LogClient   *Logger
	RequestId   string
}

// 全局资源（只初始化一次）
var (
	GlobalDB    *gorm.DB
	GlobalRedis *redis.Client
)

// InitGlobal 在 main 启动时调用，只做全局资源初始化
func InitGlobal(c config.Config) {
	// 注册日志
	Logs()

	// 连接 MySQL
	dsn := fmt.Sprintf("%v:%v@tcp(%v:%v)/%v?charset=utf8mb4&parseTime=True&loc=Local",
		c.DbService.UserName,
		c.DbService.Password,
		c.DbService.Host,
		c.DbService.Port,
		c.DbService.Dbname)

	db := sqlx.NewMysql(dsn)
	if db == nil {
		panic("failed to connect mysql")
	}
	GlobalDB = db

	// 连接 Redis
	err := redisdb.NewRedisConfig(redisdb.RedisConfig{
		Addr:     fmt.Sprintf("%s:%d", c.RedisService.Host, c.RedisService.Port),
		Password: c.RedisService.Password,
		DB:       c.RedisService.Lib,
	}).InitRedis()
	if err != nil {
		panic("failed to connect redis")
	}
	GlobalRedis = redisdb.RedisClient
}

// NewServiceContext 每次请求时调用，生成带 RequestId 的上下文
func NewServiceContext(ginCtx *gin.Context) *ServiceContext {
	// 给原生 context 注入 requestId
	ctx := WithRequestId(ginCtx.Request.Context())
	ginCtx.Request = ginCtx.Request.WithContext(ctx)

	return &ServiceContext{
		GinCtx:      ginCtx,
		DbClient:    GlobalDB,
		QClient:     query.Use(GlobalDB),
		RedisClient: GlobalRedis,
		LogClient:   WithContext(ctx),
		RequestId:   GetRequestId(ctx),
	}
}
